home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / QuickTime VR / MacOS / QuickDraw™ 3D 1.0.6F4 SDK / Samples / SampleCode / Geometry Samples / Txtr_Geometry.c next >
Encoding:
C/C++ Source or Header  |  1995-11-13  |  24.3 KB  |  917 lines  |  [TEXT/MPCC]

  1. /*
  2.  *    Txtr_Geometry.c
  3.  *
  4.  *    This is a simple library illustrating trigrid and box geometries. The trigrids
  5.  *    represented are Square, Torus, Wavey Torus, Splash, Sphere, Cone, Pipe, Steps,
  6.  *    and Spring.
  7.  *
  8.  *    NewLibraryTriGrid returns a trigrid geometry when kGeometryLibraryRange_Simple
  9.  *    is added to the trigrid number (0 to 8) or a trigrid with shading uv attributes
  10.  *    when kGeometryLibraryRange_UVGeoAttributes or kGeometryLibraryRange_UVFaceAttributes
  11.  *    is added to the trigrid number.
  12.  *
  13.  *    Note: The calculation of uv's may be flipping the texture.
  14.  *
  15.  *
  16.  *    Robert Dierkes
  17.  *    © 1995 Apple Computer, Inc.
  18.  *
  19.  *     03/22/95    RDD        Created.
  20.  *     09/20/95    RDD        Cleanup.
  21.  *     11/13/95    RDD        Changed macro to DebugStr.
  22.  */
  23.  
  24. /*------------------*/
  25. /*    Include Files    */
  26. /*------------------*/
  27. #include <Memory.h>
  28. #include <math.h>
  29.  
  30. #include "QD3D.h"
  31. #include "QD3DGeometry.h"
  32. #include "QD3DMath.h"
  33. #include "QD3DSet.h"
  34.  
  35. #include "Txtr_Geometry.h"
  36. #include "Txtr_Math.h"
  37. #include "Txtr_Error.h"
  38.  
  39.  
  40. /*----------------------*/
  41. /*    Local Prototypes    */
  42. /*----------------------*/
  43. static
  44. void AddVertexNormals(
  45.     unsigned long    geoNum,
  46.     TQ3TriGridData    *pTriData);
  47.  
  48.  
  49.  
  50. unsigned long GetLibraryMaxSimpleBox(void)
  51. {
  52.     return kGeometryLibrary_BoxMaxSimple;
  53. }
  54.  
  55.  
  56. unsigned long GetLibraryMaxSimpleTriGrid(void)
  57. {
  58.     return kGeometryLibrary_TriGridMaxSimple;
  59. }
  60.  
  61.  
  62.  
  63. TQ3GeometryObject NewLibraryBox(
  64.             unsigned long        num)
  65. {
  66.     TQ3GeometryObject    geometryObject = NULL;
  67.     TQ3BoxData            boxData;
  68.  
  69.     switch (num)
  70.     {
  71.     case kGeometryLibraryRange_Simple+0:    /* Box */
  72.         Q3Point3D_Set(&boxData.origin,        -0.5,-0.5,-0.5);
  73.         Q3Vector3D_Set(&boxData.orientation, 0.0, 1.0, 0.0);
  74.         Q3Vector3D_Set(&boxData.majorAxis,     0.0, 0.0, 1.0);
  75.         Q3Vector3D_Set(&boxData.minorAxis,     1.0, 0.0, 0.0);
  76.         boxData.boxAttributeSet  = NULL;
  77.         boxData.faceAttributeSet = NULL;
  78.  
  79.         geometryObject = Q3Box_New(&boxData);
  80.         break;
  81.  
  82.     case kGeometryLibraryRange_Simple+1:    /* Skewed Box */
  83.         Q3Point3D_Set(&boxData.origin,        -0.75,-0.5,-0.75);
  84.         Q3Vector3D_Set(&boxData.orientation, 0.5,  1.0, 0.5);
  85.         Q3Vector3D_Set(&boxData.majorAxis,     0.0,  0.0, 1.0);
  86.         Q3Vector3D_Set(&boxData.minorAxis,     1.0,  0.0, 0.0);
  87.         boxData.boxAttributeSet  = NULL;
  88.         boxData.faceAttributeSet = NULL;
  89.  
  90.         geometryObject = Q3Box_New(&boxData);
  91.         break;
  92.  
  93.     default:
  94.         DebugStr("\pWarning:  NewLibraryBox ; unknown box index");
  95.         return NULL;
  96.         break;
  97.     }
  98.  
  99.     return geometryObject;
  100. }
  101.  
  102.  
  103. /*
  104.  *    NewLibraryTriGrid
  105.  *
  106.  * There are two methods below for creating trigrid vertices. If the trigrid is:
  107.  *
  108.  *    1. planar (relatively) then the vvValue (an x-coordinate) increases from vvMin to vvMax.
  109.  *    2. a cross section revolved about the Y axis then the vvValue (an angle) decreases from
  110.  *        vvMax to vvMin in a counter-clockwise manner about the axis. This puts the correct
  111.  *        side of the trigrid facing outward for texture uvs.
  112.  *
  113.  * In both cases, uuValue decreases from uuMax to uuMin from postive to negative Y.
  114.  *
  115.  *    TriGrid vertex index numbering
  116.  *
  117.  *       (i)
  118.  *        8        9        10        11
  119.  *        4        5        6        7
  120.  *        0        1        2        3
  121.  *
  122.  *
  123.  *    UVs for an upright texture continuous across the trigrid
  124.  *
  125.  *       (U,V)
  126.  *       (x,y)
  127.  *
  128.  *        ^ +        0.0, 1.0    0.33, 1.0    0.66, 1.0    1.0, 1.0
  129.  *        |        0.0, 0.5    0.33, 0.5    0.66, 0.5    1.0, 0.5
  130.  *        V -        0.0, 0.0    0.33, 0.0    0.66, 0.0    1.0, 0.0
  131.  *
  132.  *                   U -->
  133.  *                   -   +
  134.  *
  135.  *    UVs for an upright repeated texture
  136.  *
  137.  *       (U,V)
  138.  *       (x,y)
  139.  *
  140.  *        ^ +        0,2        1,2        2,2        3,2
  141.  *        |        0,1        1,1        2,1        3,1
  142.  *        V -        0,0        1,0        2,0        3,0
  143.  *
  144.  *                   U -->
  145.  *                   -   +
  146.  */
  147. TQ3GeometryObject NewLibraryTriGrid(
  148.             unsigned long        num)
  149. {
  150.     TQ3GeometryObject    geometryObject = NULL;
  151.     TQ3TriGridData        data;
  152.     TQ3Vertex3D            *vertices;
  153.     unsigned long        i;
  154.     float                uuValue, vvValue,
  155.                         uuMin, uuMax, uuStep,
  156.                         vvMin, vvMax, vvStep,
  157.                         radius;
  158.     TQ3Boolean            hasUVAttributes;
  159.     TQ3Param2D            param2D;
  160.     TQ3Boolean            addNormals;
  161.  
  162.     hasUVAttributes = (TQ3Boolean) (mHasUVGeoAttributes(num)  ||  mHasUVFaceAttributes(num));
  163.  
  164.     switch (num)
  165.     {
  166.         case kGeometryLibraryRange_Simple+0:        /* Flat 5x5 */
  167.         case kGeometryLibraryRange_UVGeoAttributes+0:
  168.         case kGeometryLibraryRange_UVFaceAttributes+0:
  169.         case kGeometryLibraryRange_Simple+3:        /* Splash */
  170.         case kGeometryLibraryRange_UVGeoAttributes+3:
  171.         case kGeometryLibraryRange_UVFaceAttributes+3:
  172.         case kGeometryLibraryRange_Simple+7:        /* Steps */
  173.         case kGeometryLibraryRange_UVGeoAttributes+7:
  174.         case kGeometryLibraryRange_UVFaceAttributes+7:
  175.         {
  176.             addNormals = kQ3False;
  177.  
  178.             /* Setup min, max and step values trigrid vertex u & v values */
  179.             switch (num)
  180.             {
  181.             /**
  182.              ** Flat 5x5
  183.              **/
  184.             case kGeometryLibraryRange_Simple+0:
  185.             case kGeometryLibraryRange_UVGeoAttributes+0:
  186.             case kGeometryLibraryRange_UVFaceAttributes+0:
  187.  
  188.                 /*
  189.                  * uuValue is an x-coordinate
  190.                  * vvValue is a  y-coordinate
  191.                  */
  192.                 uuMin = -0.5;
  193.                 uuMax =  0.5;
  194.                 uuStep = 0.25;
  195.  
  196.                 vvMin = -0.5;
  197.                 vvMax =  0.5;
  198.                 vvStep = 0.25;
  199.             break;
  200.  
  201.             /**
  202.              ** Splash
  203.              **/
  204.             case kGeometryLibraryRange_Simple+3:
  205.             case kGeometryLibraryRange_UVGeoAttributes+3:
  206.             case kGeometryLibraryRange_UVFaceAttributes+3:
  207.  
  208.                 addNormals = kQ3True;
  209.  
  210.                 /*
  211.                  * uuValue is an x-coordinate
  212.                  * vvValue is a  y-coordinate
  213.                  */
  214.                 uuMin = -3.5;
  215.                 uuMax =  3.5;
  216.                 vvMin = -3.5;
  217.                 vvMax =  3.5;
  218.                 if (hasUVAttributes) {
  219.                     uuStep = 0.35;
  220.                     vvStep = 0.35;
  221.                 } else {
  222.                     uuStep = 0.25;
  223.                     vvStep = 0.25;
  224.                 }
  225.                 break;
  226.  
  227.             /**
  228.              ** Steps
  229.              **/
  230.             case kGeometryLibraryRange_Simple+7:
  231.             case kGeometryLibraryRange_UVGeoAttributes+7:
  232.             case kGeometryLibraryRange_UVFaceAttributes+7:
  233.  
  234.                 /*
  235.                  * uuValue is an x-coordinate
  236.                  * vvValue is a  y-coordinate
  237.                  */
  238.                 #define    kStepScale     0.2
  239.  
  240.                 uuMin = -4.5;
  241.                 uuMax =  4.5;
  242.                 uuStep = 0.5;
  243.  
  244.                 vvMin = -4.5;
  245.                 vvMax =  4.5;
  246.                 vvStep = 0.5;
  247.                 break;
  248.  
  249.             default:
  250.                 DebugStr("\pWarning:  NewLibraryTriGrid ; unknown flat trigrid index");
  251.                 return NULL;
  252.                 break;
  253.             }
  254.  
  255.  
  256.             /* Setup TQ3TriGridData */
  257.             data.numRows        = (unsigned long) ((vvMax - vvMin) / vvStep) + 1;
  258.             data.numColumns        = (unsigned long) ((uuMax - uuMin) / uuStep) + 1;
  259.             data.facetAttributeSet    = NULL;
  260.             data.triGridAttributeSet= NULL;
  261.  
  262.             data.vertices = (TQ3Vertex3D *) NewPtrClear (data.numRows * data.numColumns * sizeof(TQ3Vertex3D));
  263.             if (data.vertices == NULL)
  264.             {
  265.                 ERROR_DEBUG_STR("Error:  NewLibraryTriGrid ; Out of memory for triGrid vertices, geometry library number");
  266.                 return NULL;
  267.             }
  268.  
  269.             /* Set trigrid vertices and shading UVs, if it hasUVAttributes */
  270.             vertices = data.vertices;
  271.             i = 0;
  272.             for (vvValue = vvMin; vvValue <= vvMax; vvValue += vvStep)
  273.             {
  274.                 for (uuValue = uuMin; uuValue <= uuMax; uuValue += uuStep)
  275.                 {
  276.                     switch (num)
  277.                     {
  278.                     /* Flat 5x5 */
  279.                     case kGeometryLibraryRange_Simple+0:
  280.                     case kGeometryLibraryRange_UVGeoAttributes+0:
  281.                     case kGeometryLibraryRange_UVFaceAttributes+0:
  282.                         vertices[i].point.x = uuValue;
  283.                         vertices[i].point.y = vvValue;
  284.                         vertices[i].point.z = 0;
  285.                     break;
  286.  
  287.                     /* Splash */
  288.                     case kGeometryLibraryRange_Simple+3:
  289.                     case kGeometryLibraryRange_UVGeoAttributes+3:
  290.                     case kGeometryLibraryRange_UVFaceAttributes+3:
  291.                         vertices[i].point.x = uuValue;
  292.                         vertices[i].point.y = vvValue;
  293.                         vertices[i].point.z = 1.5 * uMath_Sin_Deg(48.0 * uuValue * vvValue) *
  294.                                                     uMath_Cos_Deg(48.0 * uuValue * vvValue);
  295.                     break;
  296.  
  297.                     /* Steps */
  298.                     case kGeometryLibraryRange_Simple+7:
  299.                     case kGeometryLibraryRange_UVGeoAttributes+7:
  300.                     case kGeometryLibraryRange_UVFaceAttributes+7:
  301.                         vertices[i].point.x = uuValue;
  302.                         vertices[i].point.y = vvValue;
  303.                         vertices[i].point.z = kStepScale * (((long) uuValue) % ((data.numRows-1)/2)) *
  304.                                                            (((long) vvValue) % ((data.numColumns-1)/2));
  305.                     break;
  306.                     }
  307.  
  308.                     if (hasUVAttributes)
  309.                     {
  310.                         if (mHasUVGeoAttributes(num))
  311.                         {
  312.                             param2D.u = (uuValue - uuMin) / (uuMax - uuMin);
  313.                             param2D.v = (vvValue - vvMin) / (vvMax - vvMin);
  314.                         }
  315.                         else /* mHasUVFaceAttributes */
  316.                         {
  317.                             param2D.u = i % data.numColumns;
  318.                             param2D.v = i / data.numColumns;
  319.                         }
  320.  
  321.                         vertices[i].attributeSet = Q3AttributeSet_New();
  322.                         if (vertices[i].attributeSet != NULL)
  323.                             Q3AttributeSet_Add(vertices[i].attributeSet, kQ3AttributeTypeShadingUV, ¶m2D);
  324.                     }
  325.                     else
  326.                         vertices[i].attributeSet = NULL;
  327.  
  328.                     i++;
  329.                 }
  330.             }
  331.  
  332.             if (addNormals)
  333.                 AddVertexNormals(num, &data);
  334.  
  335.             geometryObject = Q3TriGrid_New (&data);
  336.  
  337.             if (hasUVAttributes)
  338.             {
  339.                 for (i = 0; i < data.numRows * data.numColumns; i++)
  340.                 {
  341.                     if (vertices[i].attributeSet != NULL)
  342.                         Q3Object_Dispose(vertices[i].attributeSet);
  343.                 }
  344.             }
  345.             DisposePtr ((void *) vertices);
  346.         }
  347.         break;
  348.  
  349.         case kGeometryLibraryRange_Simple+1:        /* Torus */
  350.         case kGeometryLibraryRange_UVGeoAttributes+1:
  351.         case kGeometryLibraryRange_UVFaceAttributes+1:
  352.         case kGeometryLibraryRange_Simple+2:        /* Wavey Torus */
  353.         case kGeometryLibraryRange_UVGeoAttributes+2:
  354.         case kGeometryLibraryRange_UVFaceAttributes+2:
  355.         case kGeometryLibraryRange_Simple+4:        /* Sphere */
  356.         case kGeometryLibraryRange_UVGeoAttributes+4:
  357.         case kGeometryLibraryRange_UVFaceAttributes+4:
  358.         case kGeometryLibraryRange_Simple+5:        /* Cone */
  359.         case kGeometryLibraryRange_UVGeoAttributes+5:
  360.         case kGeometryLibraryRange_UVFaceAttributes+5:
  361.         case kGeometryLibraryRange_Simple+6:        /* Pipe */
  362.         case kGeometryLibraryRange_UVGeoAttributes+6:
  363.         case kGeometryLibraryRange_UVFaceAttributes+6:
  364.         case kGeometryLibraryRange_Simple+8:        /* Spring */
  365.         case kGeometryLibraryRange_UVGeoAttributes+8:
  366.         case kGeometryLibraryRange_UVFaceAttributes+8:
  367.         {
  368.             /* Setup min, max and step values trigrid vertex u & v values */
  369.             switch (num)
  370.             {
  371.             /**
  372.              ** Torus
  373.              **/
  374.             case kGeometryLibraryRange_Simple+1:
  375.             case kGeometryLibraryRange_UVGeoAttributes+1:
  376.             case kGeometryLibraryRange_UVFaceAttributes+1:
  377.             /**
  378.              ** Wavey Torus
  379.              **/
  380.             case kGeometryLibraryRange_Simple+2:
  381.             case kGeometryLibraryRange_UVGeoAttributes+2:
  382.             case kGeometryLibraryRange_UVFaceAttributes+2:
  383.  
  384.                 addNormals = kQ3True;
  385.  
  386.                 /*
  387.                  * uuValue is used to generate each circular cross section about the y axis
  388.                  * vvValue is used to revolve the circular cross section about the torus' center
  389.                  */
  390.                 #define    kTorusCrossRadius     0.5
  391.                 #define    kTorusInnerRadius     1.0
  392.                 #define    kTorusWaveyAmpRadius 5.0
  393.  
  394.                 uuMin =    0.0;
  395.                 uuMax =  360.0;
  396.                 vvMin = -180.0;
  397.                 vvMax =  180.0;
  398.                 if (hasUVAttributes) {
  399.                     uuStep = 12.0;    /* 10.0; */
  400.                     vvStep = 12.0;    /* 10.0; */
  401.                 } else {
  402.                     uuStep = 10.0;
  403.                     vvStep = 10.0;
  404.                 }
  405.                 break;
  406.  
  407.             /**
  408.              ** Sphere
  409.              **/
  410.             case kGeometryLibraryRange_Simple+4:
  411.             case kGeometryLibraryRange_UVGeoAttributes+4:
  412.             case kGeometryLibraryRange_UVFaceAttributes+4:
  413.  
  414.                 addNormals = kQ3True;
  415.  
  416.                 /*
  417.                  * uuValue is an angle used to revolve the cross section about the y axis
  418.                  * vvValue is an angle used to generate each half circular cross section
  419.                  */
  420.                 uuMin =    0.0;
  421.                 uuMax =  360.0;
  422.                 vvMin = - 90.0;
  423.                 vvMax =   90.0;
  424.                 if (hasUVAttributes) {
  425.                     uuStep =  12.0;    /* 10.0; */
  426.                     vvStep =  12.0;    /* 10.0; */
  427.                 } else {
  428.                     uuStep =   9.0;
  429.                     vvStep =   9.0;
  430.                 }
  431.                 radius = 1.0;
  432.                 break;
  433.  
  434.             /**
  435.              ** Cone
  436.              **/
  437.             case kGeometryLibraryRange_Simple+5:
  438.             case kGeometryLibraryRange_UVGeoAttributes+5:
  439.             case kGeometryLibraryRange_UVFaceAttributes+5:
  440.  
  441.                 addNormals = kQ3True;
  442.  
  443.                 /*
  444.                  * vvValue is the length of the cone side from point to the edge
  445.                  * uuValue is an angle used to revolve the cross section about the y axis
  446.                  */
  447.                 if (hasUVAttributes) {
  448.                     uuStep = 24.0;    /* 15.0; */
  449.                     vvStep =  0.25;
  450.                 } else {
  451.                     uuStep = 10.0;
  452.                     vvStep =  0.25;
  453.                 }
  454.                 uuMin =   0.0;
  455.                 uuMax = 360.0;
  456.                 vvMin = -vvStep;
  457.                 vvMax =   2.0;
  458.  
  459.                 radius =  0.5;
  460.                 break;
  461.  
  462.             /**
  463.              ** Pipe
  464.              **/
  465.             case kGeometryLibraryRange_Simple+6:
  466.             case kGeometryLibraryRange_UVGeoAttributes+6:
  467.             case kGeometryLibraryRange_UVFaceAttributes+6:
  468.  
  469.                 addNormals = kQ3True;
  470.  
  471.                 /*
  472.                  * uuValue is used to revolve the line cross section about the y axis
  473.                  * vvValue is used to generate the length of the pipe
  474.                  */
  475.                 if (hasUVAttributes) {
  476.                     uuStep = 20.0;    /* 10.0; */
  477.                     vvStep =  0.5;
  478.                 } else {
  479.                     uuStep = 10.0;    /* 15.0; */
  480.                     vvStep =  0.3;
  481.                 }
  482.                 uuMin =   0.0;
  483.                 uuMax = 360.0;
  484.                 vvMin = - 1.5;
  485.                 vvMax =   1.5;
  486. #ifdef    FINISH_THIS
  487.                 vvMin = - 1.5 - vvStep;
  488.                 vvMax =   1.5 + vvStep;
  489. #else    /* FINISH_THIS */
  490.                 vvMin = - 1.5;
  491.                 vvMax =   1.5;
  492. #endif    /* FINISH_THIS */
  493.                 radius =  1.0;
  494.                 break;
  495.  
  496.             /**
  497.              ** Spring
  498.              **/
  499.             case kGeometryLibraryRange_Simple+8:
  500.             case kGeometryLibraryRange_UVGeoAttributes+8:
  501.             case kGeometryLibraryRange_UVFaceAttributes+8:
  502.  
  503.                 addNormals = kQ3True;
  504.  
  505.                 /*
  506.                  * uuValue is used to revolve the circular cross section about the springs' axis
  507.                  * vvValue is used to generate each circular cross section
  508.                  */
  509.                 #define    kSpringCrossRadius     0.25
  510.                 #define    kSpringInnerRadius     1.0
  511.                 #define    kSpringSpacing         3.5*kSpringCrossRadius
  512.  
  513.                 uuMin = - 90.0;
  514.                 uuMax =  810.0;
  515.                 vvMin = -180.0;
  516.                 vvMax =  180.0;
  517.                 if (hasUVAttributes) {
  518.                     uuStep = 15.0;    /* 30.0; */
  519.                     vvStep = 30.0;
  520.                 } else {
  521.                     uuStep = 15.0;    /* 20.0; */
  522.                     vvStep = 15.0;
  523.                 }
  524.                 break;
  525.  
  526.             default:
  527.                 DebugStr("\pWarning: NewLibraryTriGrid ; unknown revolved trigrid index");
  528.                 return NULL;
  529.                 break;
  530.             }
  531.  
  532.  
  533.             /* Setup TQ3TriGridData */
  534.             data.numRows        = (unsigned long) ((vvMax - vvMin) / vvStep) + 1;
  535.             data.numColumns        = (unsigned long) ((uuMax - uuMin) / uuStep) + 1;
  536.             data.facetAttributeSet    = NULL;
  537.             data.triGridAttributeSet= NULL;
  538.  
  539.             data.vertices = (TQ3Vertex3D *) NewPtrClear (data.numRows * data.numColumns * sizeof(TQ3Vertex3D));
  540.             if (data.vertices == NULL)
  541.             {
  542.                 ERROR_DEBUG_STR("Error:  NewLibraryTriGrid ; Out of memory for triGrid vertices.");
  543.                 return NULL;
  544.             }
  545.  
  546.             /* Set trigrid vertices and shading UVs, if it hasUVAttributes */
  547.             vertices = data.vertices;
  548.             i = 0;
  549.             for (vvValue = vvMin; vvValue <= vvMax; vvValue += vvStep)
  550.             {
  551.                 for (uuValue = uuMax; uuValue >= uuMin; uuValue -= uuStep)
  552.                 {
  553.                     switch (num)
  554.                     {
  555.                     /* Torus */
  556.                     case kGeometryLibraryRange_Simple+1:
  557.                     case kGeometryLibraryRange_UVGeoAttributes+1:
  558.                     case kGeometryLibraryRange_UVFaceAttributes+1:
  559.                         vertices[i].point.x = (uMath_Cos_Deg(vvValue) * kTorusCrossRadius + kTorusInnerRadius) * uMath_Cos_Deg(uuValue);
  560.                         vertices[i].point.y =  uMath_Sin_Deg(vvValue) * kTorusCrossRadius;
  561.                         vertices[i].point.z = (uMath_Cos_Deg(vvValue) * kTorusCrossRadius + kTorusInnerRadius) * uMath_Sin_Deg(uuValue);
  562.                     break;
  563.  
  564.                     /* Wavey Torus */
  565.                     case kGeometryLibraryRange_Simple+2:
  566.                     case kGeometryLibraryRange_UVGeoAttributes+2:
  567.                     case kGeometryLibraryRange_UVFaceAttributes+2:
  568.                         radius = kTorusCrossRadius / kTorusWaveyAmpRadius * uMath_Sin_Deg(kTorusWaveyAmpRadius * uuValue) + kTorusCrossRadius;
  569.                         vertices[i].point.x = (uMath_Cos_Deg(vvValue) * radius + kTorusInnerRadius) * uMath_Cos_Deg(uuValue);
  570.                         vertices[i].point.y =  uMath_Sin_Deg(vvValue) * radius;
  571.                         vertices[i].point.z = (uMath_Cos_Deg(vvValue) * radius + kTorusInnerRadius) * uMath_Sin_Deg(uuValue);
  572.                     break;
  573.  
  574.                     /* Sphere */
  575.                     case kGeometryLibraryRange_Simple+4:
  576.                     case kGeometryLibraryRange_UVGeoAttributes+4:
  577.                     case kGeometryLibraryRange_UVFaceAttributes+4:
  578.                         vertices[i].point.x = uMath_Cos_Deg(vvValue) * uMath_Cos_Deg(uuValue) * radius;
  579.                         vertices[i].point.y = uMath_Sin_Deg(vvValue) * radius;
  580.                         vertices[i].point.z = uMath_Cos_Deg(vvValue) * uMath_Sin_Deg(uuValue) * radius;
  581.                     break;
  582.  
  583.                     /* Cone */
  584.                     case kGeometryLibraryRange_Simple+5:
  585.                     case kGeometryLibraryRange_UVGeoAttributes+5:
  586.                     case kGeometryLibraryRange_UVFaceAttributes+5:
  587.                         if (vvValue < (vvMin + vvStep))
  588.                         {
  589.                             vertices[i].point.x = 0.0;
  590.                             vertices[i].point.y = vvMin + vvStep;
  591.                             vertices[i].point.z = 0.0;
  592.                         }
  593.                         else
  594.                         {
  595.                             vertices[i].point.x = (vvMax - vvValue) * uMath_Cos_Deg(uuValue) * radius;
  596.                             vertices[i].point.y =  vvValue;
  597.                             vertices[i].point.z = (vvMax - vvValue) * uMath_Sin_Deg(uuValue) * radius;
  598.                         }
  599.                     break;
  600.  
  601.                     /* Pipe */
  602.                     case kGeometryLibraryRange_Simple+6:
  603.                     case kGeometryLibraryRange_UVGeoAttributes+6:
  604.                     case kGeometryLibraryRange_UVFaceAttributes+6:
  605. #ifdef    FINISH_THIS
  606.                         if (vvValue < (vvMin + vvStep))
  607.                         {
  608.                             vertices[i].point.x = 0.0;
  609.                             vertices[i].point.y = vvMin + vvStep;
  610.                             vertices[i].point.z = 0.0;
  611.                         }
  612.                         else
  613.                         if (vvValue > (vvMax - vvStep))
  614.                         {
  615.                             vertices[i].point.x = 0.0;
  616.                             vertices[i].point.y = vvMax - vvStep;
  617.                             vertices[i].point.z = 0.0;
  618.                         }
  619.                         else
  620.                         {
  621.                             vertices[i].point.x = uMath_Cos_Deg(uuValue) * radius;
  622.                             vertices[i].point.y = vvValue;
  623.                             vertices[i].point.z = uMath_Sin_Deg(uuValue) * radius;
  624.                         }
  625. #else    /* FINISH_THIS */
  626.                         vertices[i].point.x = radius * uMath_Cos_Deg(uuValue);
  627.                         vertices[i].point.y = vvValue;
  628.                         vertices[i].point.z = radius * uMath_Sin_Deg(uuValue);
  629. #endif    /* FINISH_THIS */
  630.                     break;
  631.  
  632.                     /* Spring */
  633.                     case kGeometryLibraryRange_Simple+8:
  634.                     case kGeometryLibraryRange_UVGeoAttributes+8:
  635.                     case kGeometryLibraryRange_UVFaceAttributes+8:
  636.                         vertices[i].point.x = (uMath_Cos_Deg(vvValue) * kSpringCrossRadius + kSpringInnerRadius) * uMath_Cos_Deg(uuValue);
  637.                         vertices[i].point.y =  uMath_Sin_Deg(vvValue) * kSpringCrossRadius + kSpringSpacing * uuValue/360.0;
  638.                         vertices[i].point.z = (uMath_Cos_Deg(vvValue) * kSpringCrossRadius + kSpringInnerRadius) * uMath_Sin_Deg(uuValue);
  639.                     break;
  640.                     }
  641.  
  642.                     if (hasUVAttributes)
  643.                     {
  644.                         if (mHasUVGeoAttributes(num))
  645.                         {
  646.                             param2D.u = 1.0 - ((uuValue - uuMin) / (uuMax - uuMin));
  647.                             param2D.v = (vvValue - vvMin) / (vvMax - vvMin);
  648.                         }
  649.                         else /* mHasUVFaceAttributes */
  650.                         {
  651.                             param2D.u = i % data.numColumns;
  652.                             param2D.v = i / data.numColumns;
  653.                         }
  654.  
  655.                         vertices[i].attributeSet = Q3AttributeSet_New();
  656.                         if (vertices[i].attributeSet != NULL)
  657.                             Q3AttributeSet_Add(vertices[i].attributeSet, kQ3AttributeTypeShadingUV, ¶m2D);
  658.                     }
  659.                     else
  660.                         vertices[i].attributeSet = NULL;
  661.  
  662.                     i++;
  663.                 }
  664.             }
  665.  
  666.             if (addNormals)
  667.                 AddVertexNormals(num, &data);
  668.  
  669.             geometryObject = Q3TriGrid_New (&data);
  670.  
  671.             if (hasUVAttributes)
  672.             {
  673.                 for (i = 0; i < data.numRows * data.numColumns; i++)
  674.                 {
  675.                     if (vertices[i].attributeSet != NULL)
  676.                         Q3Object_Dispose(vertices[i].attributeSet);
  677.                 }
  678.             }
  679.             DisposePtr ((void *) vertices);
  680.         }
  681.         break;
  682.  
  683.         default:
  684.             DebugStr("\pWarning:  NewLibraryTriGrid ; index unimplemented ");
  685.             break;
  686.     }
  687.  
  688.     return geometryObject;
  689. }
  690.  
  691.  
  692. void AddVertexNormals(
  693.     unsigned long    geoNum,
  694.     TQ3TriGridData    *pTriData)
  695. {
  696.     TQ3Vector3D        vector3D;
  697.     TQ3Point3D        point3D;
  698.     TQ3Vertex3D        *pVertices;
  699.     unsigned long    i,
  700.                     j,
  701.                     k;
  702.  
  703.     pVertices = pTriData->vertices;
  704.  
  705.     if (
  706.         /* Torus */
  707.         geoNum == kGeometryLibraryRange_Simple+1            ||
  708.         geoNum == kGeometryLibraryRange_UVGeoAttributes+1    ||
  709.         geoNum == kGeometryLibraryRange_UVFaceAttributes+1    ||
  710.         /* Wavey Torus */
  711.         geoNum == kGeometryLibraryRange_Simple+2              ||
  712.         geoNum == kGeometryLibraryRange_UVGeoAttributes+2    ||
  713.         geoNum == kGeometryLibraryRange_UVFaceAttributes+2    ||
  714.         /* Spring */
  715.         geoNum == kGeometryLibraryRange_Simple+8              ||
  716.         geoNum == kGeometryLibraryRange_UVGeoAttributes+8    ||
  717.         geoNum == kGeometryLibraryRange_UVFaceAttributes+8
  718.         )
  719.     {
  720.         unsigned long    i2;
  721.  
  722.         i2 = pTriData->numColumns * (pTriData->numRows/2);
  723.  
  724.         #define    p1    pVertices[i].point
  725.         #define    p2    pVertices[i2].point
  726.  
  727.         i = 0;
  728.         for (k = 0; k < pTriData->numRows / 2; k++)
  729.         {
  730.             for (j = 0; j < pTriData->numColumns; j++)
  731.             {
  732.                 /* Create an attribute set for non-textured geometry */
  733.                 if (pVertices[i ].attributeSet == NULL)
  734.                     pVertices[i ].attributeSet = Q3AttributeSet_New();
  735.                 if (pVertices[i2].attributeSet == NULL)
  736.                     pVertices[i2].attributeSet = Q3AttributeSet_New();
  737.  
  738.                 switch (geoNum)
  739.                 {
  740.                 /* Torus */
  741.                 case kGeometryLibraryRange_Simple+1:
  742.                 case kGeometryLibraryRange_UVGeoAttributes+1:
  743.                 case kGeometryLibraryRange_UVFaceAttributes+1:
  744.                 /* Wavey Torus */
  745.                 case kGeometryLibraryRange_Simple+2:
  746.                 case kGeometryLibraryRange_UVGeoAttributes+2:
  747.                 case kGeometryLibraryRange_UVFaceAttributes+2:
  748.                 /* Spring */
  749.                 case kGeometryLibraryRange_Simple+8:
  750.                 case kGeometryLibraryRange_UVGeoAttributes+8:
  751.                 case kGeometryLibraryRange_UVFaceAttributes+8:
  752.                     /* point3D is midpoint */
  753.                     Q3Point3D_Set (&point3D,
  754.                         (uMath_Fabs(p2.x - p1.x) / 2) + uMath_Min(p1.x, p2.x),
  755.                         (uMath_Fabs(p2.y - p1.y) / 2) + uMath_Min(p1.y, p2.y),
  756.                         (uMath_Fabs(p2.z - p1.z) / 2) + uMath_Min(p1.z, p2.z)
  757.                         );
  758.                     Q3Point3D_Subtract(&pVertices[i].point, &point3D, &vector3D);
  759.                 break;
  760.                 }
  761.  
  762.                 if ((i % pTriData->numColumns) != (pTriData->numRows / 2))
  763.                 {
  764.                     Q3Vector3D_Normalize(&vector3D, &vector3D);
  765.                     Q3AttributeSet_Add(pVertices[i].attributeSet, kQ3AttributeTypeNormal, &vector3D);
  766.                 }
  767.  
  768.                 Q3Vector3D_Negate(&vector3D, &vector3D);
  769.                 Q3Vector3D_Normalize(&vector3D, &vector3D);
  770.                 Q3AttributeSet_Add(pVertices[i2].attributeSet, kQ3AttributeTypeNormal, &vector3D);
  771.                 i++;
  772.                 i2++;
  773.             }
  774.         }
  775.  
  776.         #undef    p1
  777.         #undef    p2
  778.  
  779.         return;
  780.     }
  781.     else
  782.     if (
  783.         /* Splash */
  784.         geoNum == kGeometryLibraryRange_Simple+3              ||
  785.         geoNum == kGeometryLibraryRange_UVGeoAttributes+3    ||
  786.         geoNum == kGeometryLibraryRange_UVFaceAttributes+3
  787.         )
  788.     {
  789.         TQ3Point3D        point3Dc,
  790.                         point3Dr;
  791.  
  792.         /*    C = numColumns
  793.          *    i = vertex index
  794.          *
  795.          *        i+C
  796.          *
  797.          *    i-1  i    i+1
  798.          *
  799.          *        i-C
  800.          */
  801.         #define    pL    pVertices[i-1].point
  802.         #define    pR    pVertices[i+1].point
  803.         #define    pT    pVertices[i+pTriData->numColumns].point
  804.         #define    pB    pVertices[i-pTriData->numColumns].point
  805.         #define    pH    point3Dc
  806.         #define    pV    point3Dr
  807.  
  808.         i = pTriData->numColumns + 1;
  809.         for (k  = 1;
  810.              k <= pTriData->numRows - 2;
  811.              k++)
  812.         {
  813.             for (j  = 1;
  814.                  j <= pTriData->numColumns - 2;
  815.                  j++)
  816.             {
  817.                 /* Create an attribute set for non-textured geometry */
  818.                 if (pVertices[i].attributeSet == NULL)
  819.                     pVertices[i].attributeSet = Q3AttributeSet_New();
  820.  
  821.                 /* point3Dc, point3Dr, point3D are midpoints */
  822.  
  823.                 /* i-1 and i+1 */
  824.                 Q3Point3D_Set (&point3Dc,
  825.                     (uMath_Fabs(pR.x - pL.x) / 2) + uMath_Min(pL.x, pR.x),
  826.                     (uMath_Fabs(pR.y - pL.y) / 2) + uMath_Min(pL.y, pR.y),
  827.                     (uMath_Fabs(pR.z - pL.z) / 2) + uMath_Min(pL.z, pR.z)
  828.                     );
  829.  
  830.                 /* i-C and i+C */
  831.                 Q3Point3D_Set (&point3Dr,
  832.                     (uMath_Fabs(pT.x - pB.x) / 2) + uMath_Min(pB.x, pT.x),
  833.                     (uMath_Fabs(pT.y - pB.y) / 2) + uMath_Min(pB.y, pT.y),
  834.                     (uMath_Fabs(pT.z - pB.z) / 2) + uMath_Min(pB.z, pT.z)
  835.                     );
  836.  
  837.                 /* point3Dc and point3Dr */
  838.                 Q3Point3D_Set (&point3D,
  839.                     (uMath_Fabs(pH.x - pV.x) / 2) + uMath_Min(pV.x, pH.x),
  840.                     (uMath_Fabs(pH.y - pV.y) / 2) + uMath_Min(pV.y, pH.y),
  841.                     (uMath_Fabs(pH.z - pV.z) / 2) + uMath_Min(pV.z, pH.z)
  842.                     );
  843.  
  844.                 Q3Point3D_Subtract(&pVertices[i].point, &point3D, &vector3D);
  845.                 Q3Vector3D_Normalize(&vector3D, &vector3D);
  846.                 Q3AttributeSet_Add(pVertices[i].attributeSet, kQ3AttributeTypeNormal, &vector3D);
  847.  
  848.                 i += ((i+2) % pTriData->numColumns == 0) ? 3 : 1;
  849.             }
  850.         }
  851.  
  852.         #undef    pL
  853.         #undef    pR
  854.         #undef    pT
  855.         #undef    pB
  856.         #undef    pH
  857.         #undef    pV
  858.  
  859.         return;
  860.     }
  861.  
  862.  
  863.     /*
  864.      *    Sphere
  865.      *    Cone
  866.      *    Pipe
  867.      */
  868.     i = 0;
  869.     for (k = 0; k < pTriData->numRows; k++)
  870.     {
  871.         for (j = 0; j < pTriData->numColumns; j++)
  872.         {
  873.             /* Create an attribute set for non-textured geometry */
  874.             if (pVertices[i].attributeSet == NULL)
  875.                 pVertices[i].attributeSet = Q3AttributeSet_New();
  876.  
  877.             switch (geoNum)
  878.             {
  879.             /* Sphere */
  880.             case kGeometryLibraryRange_Simple+4:
  881.             case kGeometryLibraryRange_UVGeoAttributes+4:
  882.             case kGeometryLibraryRange_UVFaceAttributes+4:
  883.                 Q3Point3D_Set (&point3D, 0.0, 0.0, 0.0);
  884.                 Q3Point3D_Subtract(&pVertices[i].point, &point3D, &vector3D);
  885.             break;
  886.  
  887.             /* Cone */
  888.             case kGeometryLibraryRange_Simple+5:
  889.             case kGeometryLibraryRange_UVGeoAttributes+5:
  890.             case kGeometryLibraryRange_UVFaceAttributes+5:
  891.                 Q3Point3D_Set (    &point3D,
  892.                                 0.0,
  893. /**/                            ((pVertices[i].point.y > kQ3RealZero)  ||
  894.                                  (pVertices[i].point.y == kQ3RealZero  &&
  895.                                   Q3Vector3D_Length((TQ3Vector3D *) &pVertices[i].point) == 0.5))
  896.                                     ? pVertices[i].point.y
  897.                                     : 100.0,
  898.                                 0.0);
  899.                 Q3Point3D_Subtract(&pVertices[i].point, &point3D, &vector3D);
  900.             break;
  901.  
  902.             /* Pipe */
  903.             case kGeometryLibraryRange_Simple+6:
  904.             case kGeometryLibraryRange_UVGeoAttributes+6:
  905.             case kGeometryLibraryRange_UVFaceAttributes+6:
  906.                 Q3Point3D_Set (&point3D, 0.0, pVertices[i].point.y, 0.0);
  907.                 Q3Point3D_Subtract(&pVertices[i].point, &point3D, &vector3D);
  908.             break;
  909.             }
  910.  
  911.             Q3Vector3D_Normalize(&vector3D, &vector3D);
  912.             Q3AttributeSet_Add(pVertices[i].attributeSet, kQ3AttributeTypeNormal, &vector3D);
  913.             i++;
  914.         }    /* for j */
  915.     }    /* for k */
  916. }
  917.